﻿using System;
using System.ComponentModel.Design;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using EnvDTE;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Process = System.Diagnostics.Process;
using Task = System.Threading.Tasks.Task;

namespace ATL.Nuget.Plugin
{
    /// <summary>
    /// Command handler
    /// </summary>
    internal sealed class Command1
    {
        /// <summary>
        /// Command ID.
        /// </summary>
        public const int CommandId = 0x0100;

        /// <summary>
        /// Command menu group (command set GUID).
        /// </summary>
        public static readonly Guid CommandSet = new Guid("59c912a7-4b3a-4b67-90ca-a5c0073d48be");

        /// <summary>
        /// VS Package that provides this command, not null.
        /// </summary>
        private readonly AsyncPackage package;

        /// <summary>
        /// Initializes a new instance of the <see cref="Command1"/> class.
        /// Adds our command handlers for menu (commands must exist in the command table file)
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        /// <param name="commandService">Command service to add command to, not null.</param>
        private Command1(AsyncPackage package, OleMenuCommandService commandService)
        {
            this.package = package ?? throw new ArgumentNullException(nameof(package));
            commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

            var menuCommandID = new CommandID(CommandSet, CommandId);
            var menuItem = new MenuCommand(this.Execute, menuCommandID);
            commandService.AddCommand(menuItem);
        }

        /// <summary>
        /// Gets the instance of the command.
        /// </summary>
        public static Command1 Instance
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the service provider from the owner package.
        /// </summary>
        private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
        {
            get
            {
                return this.package;
            }
        }

        /// <summary>
        /// Initializes the singleton instance of the command.
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        public static async Task InitializeAsync(AsyncPackage package)
        {
            // Switch to the main thread - the call to AddCommand in Command1's constructor requires
            // the UI thread.
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

            OleMenuCommandService commandService = await package.GetServiceAsync((typeof(IMenuCommandService))) as OleMenuCommandService;
            Instance = new Command1(package, commandService);
        }

        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private async void Execute(object sender, EventArgs e)
        {
            try
            {
                await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
                // 获取当前选中的项目
                DTE dte = await ServiceProvider.GetServiceAsync(typeof(DTE)) as DTE;
                if (dte == null)
                {
                    return;
                }

                Project selectedProject = dte.SelectedItems.Item(1).Project;

                if (selectedProject != null)
                {
                    string projectPath = selectedProject.FullName;
                    string projectDir = Path.GetDirectoryName(projectPath);

                    // 生成 DLL
                    string dllPath = Path.Combine(projectDir, "bin", "Debug", $"{selectedProject.Name}.dll");

                    // 生成 NuGet 包
                    string nugetExePath = Path.Combine(projectDir, "bin", "Debug", "nuget.exe");
                    string nuspecPath = Path.Combine(projectDir, "bin", "Debug", $"{selectedProject.Name}.nuspec");
                    DateTime now = DateTime.Now;
                    string virsion = GetDllVersion(dllPath);// $"1.0.{now.ToString("yyMMdd")}.{now.ToString("HHmmss")}";
                    string virsion_sub = virsion == "1.0.0.0" ? "1.0.0" : GetDllVersion(dllPath);//$"1.0.{now.ToString("yyMMdd")}.{now.ToString("Hmmss")}";
                    // 创建 nuspec 文件
                    string nuspecContent = $@"
                <package>
                  <metadata>
                    <id>{selectedProject.Name}</id>
                    <version>{virsion}</version>
                    <authors>{Environment.UserName}</authors>
                    <owners>{Environment.UserName}</owners>
                    <requireLicenseAcceptance>false</requireLicenseAcceptance>
                    <projectUrl>https://alink-app.feishu.cn/wiki/AxSCwq2GqiuwxAk7hoCc2vgLnMg</projectUrl>
                    <description>Description</description>
                    <releaseNotes>myreleaseNotes.</releaseNotes>
                    <copyright>$copyright$</copyright>
                    <tags>Tag</tags>
                  <dependencies>
                    <group targetFramework = "".NETFramework4.5"" />
                    <group targetFramework = "".NETFramework4.5.1"" />
                    <group targetFramework = "".NETFramework4.5.2"" />
                    <group targetFramework = "".NETFramework4.6"" />
                    <group targetFramework = "".NETFramework4.6.1"" />
                    <group targetFramework = "".NETFramework4.6.2"" />
                    <group targetFramework = "".NETFramework4.7"" />
                    <group targetFramework = "".NETFramework4.7.1"" />
                    <group targetFramework = "".NETFramework4.7.2"" />
                    <group targetFramework = "".NETFramework4.8"" />
                    <group targetFramework="".NETStandard2.1"" />
                    </dependencies>
                  </metadata>
                  <files>
                    <file src=""{dllPath}"" target=""lib/net45"" />
                    <file src=""{dllPath}"" target=""lib/net451"" />
                    <file src=""{dllPath}"" target=""lib/net452"" />
                    <file src=""{dllPath}"" target=""lib/net46"" />
                    <file src=""{dllPath}"" target=""lib/net461"" />
                    <file src=""{dllPath}"" target=""lib/net462"" />
                    <file src=""{dllPath}"" target=""lib/net47"" />
                    <file src=""{dllPath}"" target=""lib/net471"" />
                    <file src=""{dllPath}"" target=""lib/net472"" />
                    <file src=""{dllPath}"" target=""lib/net48"" />
                  </files>
                </package>";
                    File.WriteAllText(nuspecPath, nuspecContent); // 执行 nuget pack 命令
                    ProcessStartInfo nugetPackInfo = new ProcessStartInfo
                    {
                        FileName = nugetExePath,
                        Arguments = $"pack {nuspecPath}",
                        WorkingDirectory = Path.Combine(projectDir, "bin", "Debug"),
                        RedirectStandardOutput = true,
                        UseShellExecute = false,
                        CreateNoWindow = true
                    };
                    if (!File.Exists(nugetExePath))
                    {
                        CopyNugetFromResources(nugetExePath);
                    }
                    using (Process nugetPackProcess = new Process { StartInfo = nugetPackInfo })
                    {
                        nugetPackProcess.Start();
                        string output = nugetPackProcess.StandardOutput.ReadToEnd();
                        nugetPackProcess.WaitForExit();
                        if (nugetPackProcess.ExitCode == 0)
                        {
                            string nupkgPath = Path.Combine(projectDir, "bin", "Debug", $"{selectedProject.Name}.{virsion}.nupkg"); // 上传到私域 Git
                            if (!File.Exists(nupkgPath))
                            {
                                nupkgPath = Path.Combine(projectDir, $"{selectedProject.Name}.{virsion_sub}.nupkg"); // 上传到私域 Git
                                if (!File.Exists(nupkgPath))
                                {
                                    MessageBox.Show($"未找到文件{Path.Combine(projectDir, $"{selectedProject.Name}.{virsion}.nupkg")}和{nupkgPath}");
                                    return;
                                }
                            }
                            string gitUrl = "http://172.28.83.84:5000/";
                            string apiKey = "your-api-key";
                            ProcessStartInfo dotnetPushInfo = new ProcessStartInfo
                            {
                                FileName = "dotnet",
                                Arguments = $"nuget push {nupkgPath} --source {gitUrl} --api-key {apiKey}",
                                WorkingDirectory = Path.Combine(projectDir, "bin", "Debug"),
                                RedirectStandardOutput = true,
                                UseShellExecute = false,
                                CreateNoWindow = true
                            };
                            using (Process dotnetPushProcess = new Process { StartInfo = dotnetPushInfo })
                            {
                                dotnetPushProcess.Start();
                                string pushOutput = dotnetPushProcess.StandardOutput.ReadToEnd();
                                dotnetPushProcess.WaitForExit();
                                if (dotnetPushProcess.ExitCode == 0)
                                {
                                    MessageBox.Show($"{selectedProject.Name}上传成功");
                                }
                                //else if(pushOutput.Contains("409 (Conflict)"))
                                //{
                                //    DialogResult dialogResult = MessageBox.Show($"上传失败，Nuget已有{ selectedProject.Name}.{virsion}.nupkg，是否删除该包？","构件冲突",MessageBoxButtons.OKCancel);
                                //    if (dialogResult == DialogResult.OK)
                                //    {
                                //        ProcessStartInfo startInfo = new ProcessStartInfo
                                //        {
                                //            FileName = "dotnet", // 指定 nuget 命令行工具
                                //            Arguments = $"nuget delete {selectedProject.Name} {virsion} --source {gitUrl}", // 指定命令和参数
                                //            RedirectStandardOutput = true, // 重定向标准输出
                                //            RedirectStandardError = true, // 重定向标准错误
                                //            RedirectStandardInput = true, // 重定向标准输入
                                //            UseShellExecute = false, // 不使用操作系统 shell
                                //            CreateNoWindow = true, // 不创建窗口
                                //            WorkingDirectory = Path.Combine(projectDir, "bin", "Debug"),
                                //        };

                                //        // 创建 Process 对象
                                //        using (Process process = new Process { StartInfo = startInfo })
                                //        {
                                //            // 启动进程
                                //            process.Start();
                                //            process.StandardInput.WriteLine("y");

                                //            // 读取标准输出和标准错误
                                //            string output2 = process.StandardOutput.ReadToEnd();
                                //            string error = process.StandardError.ReadToEnd();

                                //            // 等待进程退出
                                //            process.WaitForExit(1000 * 10);
                                //            if (process.ExitCode == 0)
                                //            {
                                //                MessageBox.Show($"{selectedProject.Name}.{virsion}删除成功");
                                //            }
                                //        }
                                //    }
                                //}
                                else
                                {
                                    MessageBox.Show($"上传失败: {pushOutput}");
                                }
                            }
                        }
                        else
                        {
                            MessageBox.Show($"打包失败: {output}");
                        }
                    }
                }
                else
                {
                    MessageBox.Show("没有选中的项目。");
                }
                //string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
                //string title = "MyCommand1";

                //// Show a message box to prove we were here
                //VsShellUtilities.ShowMessageBox(
                //    this.package,
                //    message,
                //    title,
                //    OLEMSGICON.OLEMSGICON_INFO,
                //    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                //    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
            }
            catch (Exception ex)
            {
                MessageBox.Show($"异常: {ex.ToString()}");
            }
        }
        private static void CopyNugetFromResources(string targetPath)
        {
            // 获取资源管理器
            Assembly assembly = Assembly.GetExecutingAssembly();
            string resourceName = "VSIXProjectTest1.nuget"; // 替换为你的资源名称

            using (Stream resourceStream = assembly.GetManifestResourceStream(resourceName))
            {
                using (FileStream fileStream = new FileStream(targetPath, FileMode.Create, FileAccess.Write))
                {
                    fileStream.Write(Properties.Resources.nuget, 0, Properties.Resources.nuget.Length);
                }
            }

            Console.WriteLine("nuget.exe copied from resources to " + targetPath);
        }
        /// <summary>
        /// 读取指定 DLL 的版本号。
        /// </summary>
        /// <param name="dllPath">DLL 文件的路径。</param>
        /// <returns>返回 DLL 的版本号，如果读取失败则返回 null。</returns>
        public static string GetDllVersion(string dllPath)
        {
            try
            {
                // 加载 DLL 的 Assembly
                byte[] filedata = File.ReadAllBytes(dllPath);
                Assembly assembly = Assembly.Load(filedata);
                if(File.Exists(dllPath.Replace(".dll",".pdb")))
                {
                    byte[] pdbfiledata = File.ReadAllBytes(dllPath.Replace(".dll", ".pdb"));
                    assembly = Assembly.Load(filedata, pdbfiledata);
                }

                // 获取 Assembly 的版本信息
                Version version = assembly.GetName().Version;

                // 返回版本号
                return version.ToString();
            }
            catch (Exception ex)
            {
                // 处理异常，例如文件不存在或无法加载
                Console.WriteLine($"读取 DLL 版本号时发生错误: {ex.Message}");
                return null;
            }
        }
    }
}
